/**
 *
 */
package com.cmcc.pcap.packet.capture;


import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.cmcc.packet.entity.XdrEntity;
import com.cmcc.pcap.jpcap.capture.PacketAnalysis;
import com.google.common.collect.Lists;

/**
 * @Date 2018年8月7日 上午10:10:44
 * @author Amish
 *
 */
public class TaskContext {
	private static Logger logger = LogManager.getLogger(TaskContext.class);
//	private static JdbcTemplate jdbcTemplate;
	
	private String taskId;
	private String pcapDir;
	
	private int pcapDealThreads = 1;
	private int realPcapDealThreads = 1;
	
	private Long dealTotalBytes = 0l;
	private long totalBytes = 0;
	private Thread[] threads;

	//储存线程结果
	List<Boolean> resultList = new ArrayList<Boolean>();
	private CallBack callBack;
	private CallBack quicCallBack;
	private CallBack tcpcallBack;
	private CallBack udpcallBack;
	private CallBack sctpcallBack;
	private CallBack ngapcallBack;

	private CallBack pfcpcallBack;
	
//	static {
//		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); //
//		jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
//	}
	

	public TaskContext(String taskId,String pcapDir,CallBack callBack,CallBack quicCallBack,CallBack tcpcallBack,CallBack udpcallBack,CallBack sctpcallBack, CallBack ngapcallBack,CallBack pfcpcallBack){
		this.taskId = taskId;
		this.pcapDir = pcapDir;
		this.pcapDealThreads = 2;//PacketAnalysisConfig.getConfigAsInt("pcap.deal.threads") > 0 ? PacketAnalysisConfig.getConfigAsInt("pcap.deal.threads") : 1;
		this.callBack = callBack;
		this.quicCallBack = quicCallBack;
		this.tcpcallBack = tcpcallBack;
		this.udpcallBack = udpcallBack;
		this.sctpcallBack = sctpcallBack;
		this.ngapcallBack = ngapcallBack;
		this.pfcpcallBack = pfcpcallBack;
	}
	
	public void analysisStart(){
		File dir = new File(pcapDir);
		if( !dir.isDirectory() ){
			logger.error("the input is not a directory ");
			return;
		}
		
		File[] files = dir.listFiles(PacketAnalysis.filenameFilter);
		
		logger.info("the fileNumber is : "+files.length);
		//logger.info("the dir total length is : "+dir.length());//8192
		
		totalBytes = 0;
		for(File file : files){
			totalBytes += file.length();
			//logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
		}
		logger.info("the dir total length is : "+totalBytes);
		
		if(pcapDealThreads <= 1 ){
			realPcapDealThreads = 1;
		}else if(pcapDealThreads > files.length){
			realPcapDealThreads = files.length;//保证线程数不能大于文件数
		}else{
			realPcapDealThreads = pcapDealThreads;
		}
		logger.info("the real pacp deal threads is : "+realPcapDealThreads);

		List<File> listFiles = new ArrayList<File>(Arrays.asList(files));
		
		
		int partitionSize = listFiles.size();
		if(listFiles.size() % realPcapDealThreads > 0){
			partitionSize = listFiles.size() / realPcapDealThreads + 1;
		}else if(listFiles.size() % realPcapDealThreads == 0){
			partitionSize = listFiles.size() / realPcapDealThreads;
		}
		
		List<List<File>> subLists = Lists.partition(listFiles, partitionSize);// 利用Lists拆分数组,这里的partitionSize表示分隔后的List元素最大个数
		
		threads = new Thread[realPcapDealThreads];
		for(int i=0;i<threads.length;i++){
			//File[] subFiles = (File[])((List<File>)subLists.get(i)).toArray();
			List<File> subList = subLists.get(i);
			logger.info("pcapDealThread <"+i+"> contains files :"+subList.size()+". file list : "+subList.toString());
			
			PcapDealThread pcapDealThread = new PcapDealThread(taskId,subList,this);
			threads[i] = new Thread(pcapDealThread);
			threads[i].setDaemon(true);
			threads[i].start();	
		}
	}
	
	public void callBack(Boolean result) {
		synchronized (resultList) {
			resultList.add(result);
			if(resultList.size()==threads.length) {
				callBack.setProcessPercent("100");
				logger.info("all pcap analysis done ");
			}
		}
	}
	

	class PcapDealThread implements Runnable{
        String taskId;
        //File[] files;
        List<File> subList;
        TaskContext tc;
        public PcapDealThread(String taskId, List<File> subList, TaskContext tc){
        	this.taskId = taskId;
        	this.subList = subList;
        	this.tc = tc;
        }
        
		@Override
		public void run() {
			JCaptures jc = new JCaptures(taskId,callBack,quicCallBack,tcpcallBack,udpcallBack,sctpcallBack,ngapcallBack,pfcpcallBack);  //赋值标准id,存入数据库表中
			//long dealTotalBytes = 0;
			for(File file : subList){//TODO file 分组 分给多个jcpatures处理？
				long dealBytes = file.length();
				try{
				logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());

//					jc.complete = false;
				jc.tcp_complete = false;
				jc.udp_complete = false;
				
				jc.captureFromFile(file.getAbsolutePath(),null);
				}catch(Exception e){
					logger.error(e.getCause(),e);
				}

				String proportion ="";
				synchronized(dealTotalBytes) {
					dealTotalBytes = dealTotalBytes + dealBytes;
					proportion = PacketAnalysis.proportionCalculation(dealTotalBytes,totalBytes);
				}
				
				//将处理进度写入数据库 
				if(!"100".equals(proportion))
					callBack.setProcessPercent(proportion);
			}
			jc.stop();//显示调用stop，否则文件处理完也不会结束进程
			callBack(true);
		}
		
	}
	
}